package org.aom.util;

import java.text.MessageFormat;
import java.util.Locale;
import java.util.Map;
import java.util.MissingResourceException;
import java.util.ResourceBundle;

import javax.faces.FactoryFinder;
import javax.faces.application.Application;
import javax.faces.application.ApplicationFactory;
import javax.faces.application.FacesMessage;
import javax.faces.context.FacesContext;
import javax.faces.el.ValueBinding;
import javax.faces.webapp.UIComponentTag;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.aom.constants.Constants;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

@SuppressWarnings("deprecation")
public class FaceUtil {

	private static Logger logger = LoggerFactory.getLogger(FaceUtil.class);

	public static String getSessionId() {
		return ((HttpSession) FacesContext.getCurrentInstance()
				.getExternalContext().getSession(false)).getId();
	}

	public static Map<String, Object> getSessionMap() {
		return FacesContext.getCurrentInstance().getExternalContext()
				.getSessionMap();
	}

	public static Locale getLocale() {
		Locale locale;
		try {
			locale = FacesContext.getCurrentInstance().getViewRoot()
					.getLocale();
		} catch (Exception e) {
			logger
					.warn("Could not get locale from FacesContext (perhaps this was this called during testing?)");
			locale = Constants.LOCALE;
		}
		return locale;
	}

	public static ServletContext getServletContext() {
		return (ServletContext) FacesContext.getCurrentInstance()
				.getExternalContext().getContext();
	}

	public static HttpServletRequest getHttpServletRequest() {
		return (HttpServletRequest) FacesContext.getCurrentInstance()
				.getExternalContext().getRequest();
	}

	public static HttpServletResponse getHttpServletResponse() {
		return (HttpServletResponse) FacesContext.getCurrentInstance()
				.getExternalContext().getResponse();
	}

	public static Object getManagedBean(String beanName) {
		return getValueBinding(getJsfEl(beanName)).getValue(
				FacesContext.getCurrentInstance());
	}

	public static void resetManagedBean(String beanName) {
		getValueBinding(getJsfEl(beanName)).setValue(
				FacesContext.getCurrentInstance(), null);
	}

	public static void setManagedBeanInSession(String beanName,
			Object managedBean) {
		FacesContext.getCurrentInstance().getExternalContext().getSessionMap()
				.put(beanName, managedBean);
	}

	public static String getRequestParameter(String name) {
		return (String) FacesContext.getCurrentInstance().getExternalContext()
				.getRequestParameterMap().get(name);
	}

	public static void addInfoMessage(String msg) {
		addInfoMessage(null, msg);
	}

	public static void addInfoMessage(String clientId, String msg) {
		try {
			String resMsg = BundleUtil.getLocalizedMessage(msg);
			FacesContext.getCurrentInstance()
					.addMessage(
							clientId,
							new FacesMessage(FacesMessage.SEVERITY_INFO,
									resMsg, resMsg));
		} catch (MissingResourceException mre) {
			FacesContext.getCurrentInstance().addMessage(clientId,
					new FacesMessage(FacesMessage.SEVERITY_INFO, msg, msg));
		}
	}

	public static void addErrorMessage(String msg) {
		addErrorMessage(null, msg);
	}

	public static void addErrorMessage(String clientId, String msg) {
		try {
			String resMsg = BundleUtil.getLocalizedMessage(msg);
			FacesContext.getCurrentInstance().addMessage(
					clientId,
					new FacesMessage(FacesMessage.SEVERITY_ERROR, resMsg,
							resMsg));
		} catch (MissingResourceException mre) {
			FacesContext.getCurrentInstance().addMessage(clientId,
					new FacesMessage(FacesMessage.SEVERITY_ERROR, msg, msg));
		}

	}

	public static Integer evalInt(String el) {
		if (el == null) {
			return null;
		}

		if (UIComponentTag.isValueReference(el)) {
			Object value = getElValue(el);

			if (value == null) {
				return null;
			} else if (value instanceof Integer) {
				return (Integer) value;
			} else {
				return new Integer(value.toString());
			}
		} else {
			return new Integer(el);
		}
	}

	public static void setRequestAttribute(String attName, Object attValue) {
		getServletRequest().setAttribute(attName, attValue);
	}

	public static Object getSessionAttribute(String attName) {
		return getServletRequest().getSession().getAttribute(attName);
	}

	public static void removeSessionAttribute(String attName) {
		getServletRequest().getSession().removeAttribute(attName);
	}

	public static HttpServletResponse getServletResponse() {
		return (HttpServletResponse) FacesContext.getCurrentInstance()
				.getExternalContext().getResponse();
	}

	public static HttpServletRequest getServletResquest() {
		return (HttpServletRequest) FacesContext.getCurrentInstance()
				.getExternalContext().getRequest();
	}

	private static Application getApplication() {
		ApplicationFactory appFactory = (ApplicationFactory) FactoryFinder
				.getFactory(FactoryFinder.APPLICATION_FACTORY);
		return appFactory.getApplication();
	}

	private static ValueBinding getValueBinding(String el) {
		return getApplication().createValueBinding(el);
	}

	private static HttpServletRequest getServletRequest() {
		return (HttpServletRequest) FacesContext.getCurrentInstance()
				.getExternalContext().getRequest();
	}

	private static Object getElValue(String el) {
		return getValueBinding(el).getValue(FacesContext.getCurrentInstance());
	}

	private static String getJsfEl(String value) {
		return "#{" + value + "}";
	}

	public static String getLocalizedMessage(String key, String[] params) {
		String rawString = getLocalizedMessage(key);
		MessageFormat format = new MessageFormat(rawString);
		return format.format(params);
	}

	public static String getLocalizedMessage(String key) {
		FacesContext context = FacesContext.getCurrentInstance();
		String bundleName;
		if (context == null) {
			bundleName = Constants.RESOURCE_FILE;
		} else {
			bundleName = context.getApplication().getMessageBundle();
		}
		ResourceBundle rb = ResourceBundle.getBundle(bundleName, getLocale());
		return rb.getString(key);
	}

}
